package gbench.appdemo.myworld.market.store;

import static gbench.common.tree.LittleTree.IRecord.REC;
import static gbench.common.tree.LittleTree.IRecord.pvtclc;

import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import gbench.appdemo.myworld.market.commodity.Commodity;
import gbench.common.tree.LittleTree.IRecord;

/**
 * 
 * @author gbench
 *
 */
public class FinanceAccounting {
    
    /**
     * 
     * @param onlineStore
     */
    public FinanceAccounting(OnlineStore onlineStore) {
        this.onlineStore = onlineStore;
    }

    /**
     * 
     * @param commodity
     * @return
     */
    public FinanceAccounting  post(final String name, CommodityAccountName statusA,CommodityAccountName statusB, Double quantity) {
        this.withTransaction(rec -> Stream.of(
            rec.derive(REC("drcr", 0, "name", name, "status", statusA, "quantity", quantity)),
            rec.derive(REC("drcr", 1, "name", name, "status", statusB, "quantity", quantity))
         ));
        return this;
    }
    
    /**
     * 
     * @param cs
     */
    public FinanceAccounting withTransaction(final Function<IRecord,Stream<IRecord>> callbacks) {
        this.transDatabase.withTransaction(callbacks);
        return this;
    }
    
    /**
     * 获取交易记录
     * @return
     */
    public Stream<IRecord> getTransDatabase(){
        return this.transDatabase.getTransactions();
    }
    
    /**
     * 获取交易记录
     * @return
     */
    public Stream<IRecord> getTransactions(Commodity commodity){
        return this.getTransDatabase().filter(e->commodity.getName().equals(e.str("name")));
    }
    
    /**
     * 获取交易记录
     * @return
     */
    public IRecord trialBalance(Commodity commodity){
        return this.getTransactions(commodity).collect(pvtclc("status","drcr"));
    }
    
    /**
     * 获取交易记录
     * @return
     */
    public List<IRecord> trialBalance2(Commodity commodity){
        List<IRecord> recs = new LinkedList<>();
        this.getTransactions(commodity).collect(pvtclc("status","drcr"))
        .dfs_forall((String path, List<IRecord> rr)->{
            final var total = rr.stream().map(e->e.dbl("quantity"))
                .collect(Collectors.summarizingDouble(e->e)).getSum();
            recs.add(REC("name",commodity.getName(),"path",path,"total",total));
        });
        
        return recs;
    }
    
    /**
     * 导入产品
     * @param commodity
     * @param quantity
     */
    public void increment(Commodity commodity,Number quantity) {
       this.post(commodity.getName(), CommodityAccountName.AVAILABLE, CommodityAccountName.INVENTORY, quantity.doubleValue());
    }
    
    /**
     * 导入产品
     * @param commodity
     * @param quantity
     */
    public void decrement(Commodity commodity,Number quantity) {
       this.post(commodity.getName(), CommodityAccountName.INVENTORY,CommodityAccountName.AVAILABLE, quantity.doubleValue());
    }
    
    /**
     * 导入产品
     * @param commodity
     * @param quantity
     */
    public void free(Commodity commodity,Number quantity) {
        this.post(commodity.getName(), CommodityAccountName.FREEZED, CommodityAccountName.AVAILABLE, quantity.doubleValue());
    }
    
    /**
     * 导入产品
     * @param commodity
     * @param quantity
     */
    public void close(Commodity commodity,Number quantity) {
        this.post(commodity.getName(), CommodityAccountName.CLOSED, CommodityAccountName.DELIVERD, quantity.doubleValue());
    }
    
    /**
     * 导入产品
     * @param commodity
     * @param quantity
     */
    public void deliver(Commodity commodity,Number quantity) {
        this.post(commodity.getName(), CommodityAccountName.DELIVERD, CommodityAccountName.RLEASED, quantity.doubleValue());
    }
    
    /**
     * 导入产品
     * @param commodity
     * @param quantity
     */
    public void release(Commodity commodity,Number quantity) {
        this.post(commodity.getName(), CommodityAccountName.RLEASED, CommodityAccountName.FREEZED, quantity.doubleValue());
    }
    
    /**
     * 商品摘要状态
     * @author gbench
     *
     */
    public enum CommodityAccountName{
        FREEZED,
        RLEASED,
        DELIVERD,
        CLOSED,
        AVAILABLE,
        INVENTORY
    };
    
    public OnlineStore getOnlineStore() {
        return onlineStore;
    }

    public void setOnlineStore(OnlineStore onlineStore) {
        this.onlineStore = onlineStore;
    }
    
    private OnlineStore onlineStore;
    
    public DrcrTransactionDatabase transDatabase = new DrcrTransactionDatabase(onlineStore);
}